home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Think Class Libraries / Waste TCL r2 / CWASTEEditTask.cp < prev    next >
Encoding:
Text File  |  1994-11-30  |  7.8 KB  |  346 lines  |  [TEXT/KAHL]

  1. /*
  2.  *
  3.  *    File:        CWASTEEditTask.cp
  4.  *    Module:        CWASTEEditTask method definitions
  5.  *    System:        Mark's Class Library
  6.  *    Evironment:    MacOS 7.0/THINK C 7.0/TCL 2.0
  7.  *    Author:        Mark Alldritt
  8.  *
  9.  *
  10.  *        Copyright © 1994    All Rights Reserved
  11.  *        Mark Alldritt
  12.  *        1571 Deep Cove Road
  13.  *        N. Vancouver, B.C. CANADA
  14.  *
  15.  *    
  16.  *    Description:
  17.  *
  18.  *  This class modifies the CTextEditTask to allow it to work with CWASTEText.
  19.  *
  20.  *
  21.  *    Acknowledgemets:
  22.  *
  23.  *    None.
  24.  *
  25.  *
  26.  *    Notes:
  27.  *
  28.  *
  29.  *    Edit History:
  30.  *
  31.  *    V1-0.0    Mark Alldritt    10-May-1994
  32.  *    - Initial version of module.
  33.  *  V1.0.1  Modifications by Dan Crevier to TCL 2.0
  34.  *  V1.0.2  Added code by Mark Alldritt for undo/redo
  35.  *
  36.  */
  37.  
  38.  
  39. #include "CWASTEText.h"
  40. #include "CWASTEEditTask.h"
  41.  
  42. #include <CClipboard.h>
  43.  
  44. extern CClipboard *gClipboard;
  45.  
  46. CWASTEEditTask::CWASTEEditTask(CWASTEText *aTextPane, long anEditCmd, 
  47.                                short firstTaskIndex)
  48. {
  49.     Handle    h;
  50.     
  51.     origStyleScrap = deletedStyles = insertedStyles = NULL;
  52.  
  53.     // can't call through constructor, or our SaveRange won't be called
  54.     ITextEditTask( aTextPane, anEditCmd, firstTaskIndex);
  55.  
  56.     gClipboard->GetData( 'styl', &h);
  57.     origStyleScrap = (StScrpHandle) h;
  58.  
  59. }
  60.  
  61.  
  62. CWASTEEditTask::~CWASTEEditTask()
  63. {
  64.     ForgetHandle( origStyleScrap);
  65.     ForgetHandle( deletedStyles);
  66.     ForgetHandle( insertedStyles);
  67. }
  68.  
  69.  
  70. void CWASTEEditTask::SaveRange( tRangeSelector whichRange)
  71. {
  72.     StScrpHandle    h;
  73.     long oldStart, oldEnd;
  74.     
  75.     inherited::SaveRange( whichRange);
  76.     
  77.     itsTextPane->GetSelection( &oldStart, &oldEnd);
  78.     
  79.     if (whichRange == kInsertedRange)
  80.         itsTextPane->SetSelection( inserted.start, inserted.end, FALSE);
  81.     else
  82.         itsTextPane->SetSelection( deleted.start, deleted.end, FALSE);
  83.         
  84.     h = ((CWASTEText*) itsTextPane)->GetTheStyleScrap();
  85.     
  86.     itsTextPane->SetSelection( oldStart, oldEnd, FALSE);
  87.     
  88.     if (whichRange == kInsertedRange)
  89.         insertedStyles = h;
  90.     else
  91.         deletedStyles = h;
  92.     
  93. }
  94.  
  95.  
  96. void CWASTEEditTask::RestoreRange( tRangeSelector whichRange, Boolean killData)
  97. {
  98.     Handle            text;
  99.     StScrpHandle     styles;
  100.     long            selStart, selEnd, start;
  101.     short            styleFixup;
  102.     
  103.     if (whichRange == kInsertedRange)
  104.     {
  105.         text = inserted.text;
  106.         styles = insertedStyles;
  107.         start = inserted.start;
  108.         selStart = inserted.selStart;
  109.         selEnd = inserted.selEnd;
  110.         if (killData)
  111.         {
  112.             inserted.text = NULL;
  113.             insertedStyles = NULL;
  114.         }
  115.     }
  116.     else
  117.     {
  118.         text = deleted.text;
  119.         styles = deletedStyles;
  120.         start = deleted.start;
  121.         selStart = deleted.selStart;
  122.         selEnd = deleted.selEnd;
  123.         if (killData)
  124.         {
  125.             deleted.text = NULL;
  126.             deletedStyles = NULL;
  127.         }
  128.     }
  129.     
  130.     if (text)
  131.     {
  132.         // Due to backspacing, the save styled scrap handle may
  133.         // begin with negative offsets. Before attempting to
  134.         // restore these styles we must fix up the offsets
  135.         // to start at 0.
  136.         
  137.         styleFixup = -(**styles).scrpStyleTab[0].scrpStartChar;
  138.         if (styleFixup > 0)
  139.         {
  140.             ScrpSTElement    *table = (**styles).scrpStyleTab;
  141.             short i = (**styles).scrpNStyles;
  142.             
  143.             while (--i >= 0)
  144.             { 
  145.                 table++->scrpStartChar += styleFixup;
  146.             }
  147.         }
  148.  
  149.         itsTextPane->SetSelection( start, start, TRUE);
  150.         MoveHHi( text);
  151.         HLock( text);
  152.         ((CWASTEText *)itsTextPane)->InsertWithStyle(*text, GetHandleSize( text), styles, FALSE);
  153.         HUnlock( text);
  154.     }
  155.     if (killData)
  156.     {
  157.         ForgetHandle(text);
  158.         ForgetHandle( styles);
  159.     }
  160.     itsTextPane->SetSelection( selStart, selEnd, TRUE);
  161.  
  162. }
  163.  
  164.  
  165. void CWASTEEditTask::StoreToClip( tClipSelector whichClip)
  166. {
  167.     StScrpHandle     h;
  168.  
  169.     inherited::StoreToClip( whichClip);
  170.         
  171.     if (whichClip == kOldClip)
  172.         h = origStyleScrap;
  173.     else
  174.         h = deletedStyles;
  175.  
  176.     if (h)
  177.         gClipboard->PutData( 'styl', (Handle) h);
  178.         
  179.  
  180. }
  181.  
  182.  
  183. void CWASTEEditTask::DoBackspace( void)
  184. {
  185.     long             selStart, selEnd;
  186.     ScrpSTElement     scrapEl;
  187.     WERunInfo        runInfo;
  188.     
  189.     itsTextPane->GetSelection( &selStart, &selEnd);
  190.     
  191.     /*
  192.      *    We only need to do something when the user is backspacing
  193.      *  over original text that was not selected at the start
  194.      *  of this task. When that happens, we must check the style
  195.      *  of the char being deleted. If it is different from the
  196.      *  style currently at the front of the deletedStyle handle
  197.      *  then we must insert it to the handle.
  198.      */
  199.     
  200.     if ((selStart > 0) && (selStart == deleted.start) && (selStart == selEnd))
  201.     {
  202.         WEGetRunInfo(selStart - 1, &runInfo, ((CWASTEText *)itsTextPane)->macWE);
  203.         
  204.         /* make up a style scrap element for the char to be deleted.    */
  205.         /* Then we'll see if it matches the first style in the            */
  206.         /* saved scrap. If not, we need to insert it to the scrap        */
  207.         
  208.         scrapEl.scrpStartChar = (**deletedStyles).scrpStyleTab[0].scrpStartChar-1;
  209.         scrapEl.scrpHeight = runInfo.runHeight;
  210.         scrapEl.scrpAscent = runInfo.runAscent;
  211.         /* remaining fields are equivalent to a TextStyle record    */
  212.         *(TextStyle*) &scrapEl.scrpFont = runInfo.runStyle;
  213.         
  214.         /* CheckNewStyle inserts the new style at the head of the    */
  215.         /* style scrap if its new. Otherwise, we just decrement        */
  216.         /* the starting offset for the first style. This is            */
  217.         /* faster than running through the whole table, fixing        */
  218.         /* up offsets each time the user backspaces, but we have    */
  219.         /* to be sure and fix these up later, before attempting to    */
  220.         /* use these styles                                            */
  221.         
  222.         if (!CheckNewStyle( &scrapEl, deletedStyles, TRUE))        
  223.             (**deletedStyles).scrpStyleTab[0].scrpStartChar--;
  224.     }
  225.  
  226.     inherited::DoBackspace();
  227. }
  228.  
  229.  
  230. void CWASTEEditTask::DoFwdDelete( void)
  231. {
  232.     long             selStart, selEnd, length;
  233.     ScrpSTElement     scrapEl;
  234.     WERunInfo        runInfo;
  235.     
  236.     itsTextPane->GetSelection( &selStart, &selEnd);
  237.     length = itsTextPane->GetLength();
  238.     
  239.     if ((selStart == selEnd) && (selEnd < length))
  240.     {
  241.         WEGetRunInfo(selStart - 1, &runInfo, ((CWASTEText *)itsTextPane)->macWE);
  242.  
  243.         /* make up a style scrap element for the char to be deleted.    */
  244.         /* Then we'll see if it matches the last style in the            */
  245.         /* saved scrap. If not, we need to insert it to the scrap        */
  246.         
  247.         scrapEl.scrpStartChar = deleted.end - deleted.start + 
  248.                     (**deletedStyles).scrpStyleTab[0].scrpStartChar;
  249.         scrapEl.scrpHeight = runInfo.runHeight;
  250.         scrapEl.scrpAscent = runInfo.runAscent;
  251.         /* remaining fields are equivalent to a TextStyle record    */
  252.         *(TextStyle*) &scrapEl.scrpFont = runInfo.runStyle;
  253.         
  254.         CheckNewStyle( &scrapEl, deletedStyles, FALSE);    
  255.     }
  256.     inherited::DoFwdDelete();
  257. }
  258.  
  259.  
  260. Boolean CWASTEEditTask::CheckNewStyle(ScrpSTElement *scrapEl, 
  261.                                       StScrpHandle styleH,
  262.                                       Boolean atStart)
  263. {
  264.     short     index = atStart ? 0 : (**styleH).scrpNStyles-1;
  265.     long    currSize;
  266.     Boolean wasNew = FALSE;
  267.     
  268.     /* compare scrapEl with either first or last scrapElement in scrap handle    */
  269.     /* but don't compare the scrpStartChar fields                                */
  270.     /* If they don't match, then a new ScrpSTElement is inserted                */
  271.     
  272.     if (!EqualMem( &scrapEl->scrpHeight, 
  273.             &(**styleH).scrpStyleTab[index].scrpHeight, 
  274.             sizeof(TextStyle) - sizeof(long)))
  275.     {
  276.             
  277.         currSize = GetHandleSize( (Handle) styleH);
  278.         ResizeHandleCanFail( (Handle) styleH, currSize + sizeof(ScrpSTElement));
  279.         FailMemError();
  280.         
  281.         /* if atStart, then move old styles down            */
  282.         
  283.         if (atStart)
  284.         {
  285.             BlockMove( &(**styleH).scrpStyleTab[0],
  286.                     &(**styleH).scrpStyleTab[1],
  287.                     currSize - sizeof(short));
  288.         }
  289.         else
  290.             index++; // place at end
  291.         
  292.         /* place new style in position, increment count        */
  293.         
  294.         (**styleH).scrpStyleTab[index] = *scrapEl;
  295.         (**styleH).scrpNStyles++;
  296.                 
  297.         wasNew = TRUE;
  298.     }
  299.  
  300.     return wasNew;
  301. }
  302.  
  303. void CWASTEEditTask::Undo()
  304. {
  305.     CTask::Undo();
  306.     
  307.     if (doText)
  308.     {
  309.         if (stillTyping)
  310.             CancelTyping();
  311.  
  312.         SaveRange(kInsertedRange);
  313.     
  314.         itsTextPane->Prepare();
  315.         itsTextPane->SetSelection(inserted.start, inserted.end, FALSE);
  316.         RestoreRange(kDeletedRange, FALSE);
  317.     }
  318.     
  319.     if (doClip)
  320.         StoreToClip(kOldClip);
  321. }
  322.  
  323.  
  324. void CWASTEEditTask::Redo()
  325. {
  326.     undone = FALSE;
  327.     if (editCmd == cmdNull) stillTyping = TRUE;
  328.  
  329.     if (doText)
  330.     {
  331.         itsTextPane->Prepare();
  332.         itsTextPane->SetSelection(deleted.start, deleted.end, FALSE);
  333.         RestoreRange(kInsertedRange, TRUE);
  334.  
  335.         if (editCmd == cmdNull)
  336.             stillTyping = TRUE;
  337.     }
  338.  
  339.     if (doClip)
  340.         StoreToClip(kNewClip);
  341.  
  342.     ReportChange(TRUE);
  343. }
  344.  
  345.  
  346.